TVだってコマンドラインでいじりたおしたい:HDMI CEC
https://gyazo.com/6eb46c49dba4d52b07b2b3583c5d892a
むとうたけし@関西*BSDユーザ会 (@610t) この夏休み(!?)こんなことをやっていました
https://gyazo.com/e12d65319c5f81d2a42143cc6b221b99
micro:bit歩数計の値が少ないと、ChromecastでYouTubeダンス動画を流して運動させる
YouTubeの動画が終わったらTVの電源を切りたい
Chromecast YouTube Pythonライブラリ(pychromecast)ではできなさそう
HDMI CECってあったんじゃね?
HDMI CEC
CEC = Consumer Electronics Control
HDMIで接続した機器同士を制御するための仕組み
HDMI規格のSuppliment 1
CEC専用のHDMIの13ピンを使って、1線式の双方向シリアルバスを構成する
TV、レコーダー、Chromecast、AppleTVなどの機器がこれを使ってTVの電源操作や画面の切り替えなどをしている
メーカ各社のHDMI CECベース機能
ビエラリンク パナソニック
AQUOSファミリンク シャープ
ブラビアリンク ソニー
レグザリンク 東芝
リアリンク 三菱電機
HDMI CECでできること
機器の実装によっては、使えないものもある
TVや機器の電源オンオフ
入力ソースの変更(アクティブ)
音量の変更
電源状態やアクティブ状態、音量などの各種情報の取得
リモコン操作(User Control)に相当すること
ベンダーの独自拡張機能
などなど
HDMI CECユーザ向けコマンド
CEC-O-MATICのEnd-user featureより、重複コマンドは省略。赤字はAQUOS LC-32J9で使えたもの。 One Touch Play: 電源オンと入力ソースの切り替え
Active Source: 物理アドレスで指定した機器をアクティブに
Image View On: 電源をオンに
Text View On: テキストやメニューを出さない電源オン
System Standby: 機器状態を待機(standby,≒電源オフ)に
Standby: 機器状態を待機(standby,≒電源オフ)に
Remote Control Pass Through: リモコンでの操作関連
User Control Pressed: リモコンのキーが押されたことを通知
User Control Released: リモコンのキーが話されたことを通知
One Touch Record: 録画関連
Record Off: 録画終了
Record On: 録画開始
Record Status: 録画状態の通知に利用
Record TV Screen: 現在TVでアクティブな画面を録画
Deck Control: Playbackデバイスを操作する
Give Deck Status: Playbackデバイスの状態を確認する
Desk Status: Playbackデバイスの状態を応答する (Give Deck Statusの応答)
Deck Control: Playbackデバイスを早送り、巻き戻し、停止、イジェクトする
Play: Playbackデバイスを様々なモードで再生する
Tuner Control: チューナデバイスを操作する
Give Tuner Device Status: チューナーデバイスの状態を確認する
Tuner Device Status: デバイス状態を応答する (Give Tuner Device Statusの応答)
Select Analogue Service: アナログTVのチューナサービスを選択する
Select Digital Service: デジタルTVのチューナサービスを選択する
Tuner Step Decrement: チューナーを一つ下に変更する
Tuner Step Increment: チューナーを一つ上に変更する
(Record On:)
System Audio Control: TVで使われれているオーディオアンプを操作する
Give Audio Status: オーディオの状態を確認する
Report Audio Status: オーディオの状態を応答する (Give Audio Statusの応答)
Give System Audio Mode Status: System Audio Modeの状態を確認する
System Audio Mode Status: System Audio Modeの状態を応答する (Give System Audio Mode Statusの応答)
Set System Audio Mode: System Audio Modeをオンまたはオフにする
System Audio Mode Request: ?
(User Control Pressed, User Control Released)
Device Menu Control: メニュー操作に関するコマンド
Menu Request: TVにメニューを出したり消したりするように要求
Menu Status: メニューを表示したり、消したりした時に状態を通知する
(User Control Pressed, User Control Released)
Timer Programming: Recordingデバイスのタイマーを操作する
Clear Analogue Timer: アナログタイマーのエントリを消す
Clear Digital Timer: デジタルタイマーのエントリを消す
Clear External Timer: 外部タイマーのエントリを消す
Timer Cleared Status: タイマー消去の状態を応答する (Clear * Timerの応答)
Set Analogue Timer: アナログタイマーを設定する
Set Digital Timer: デジタルタイマーを設定する
Set External Timer: 外部タイマーを設定する
Set Timer Program Title: タイマーのプログラム名を設定する
Timer Status: (Status Timerの応答)
物理アドレスと論理アドレス
機器を指定するために、各機器は動的に割り当てられる二つのアドレスを持つ
物理アドレス(Physical Address): 起動時にアドレス解決をして、4byteのアドレスが割り当てられる(例. 0.0.0.0, 1.0.0.0)
論理アドレス(Logical Address): 機器の論理的な役割に応じて、1byteのアドレスが割り当てられる(例. 0(TV), 1(Recording Device 1))
table:アドレスの例
論理アドレス デバイス むとう家の例 物理アドレスの例
0 TV Sharp AQUOS LC-32J9 0.0.0.0
1 Recording Device 1 RPI Raspbian 3.0.0.0
2 Recording Device 2 Toshiba REGZA RD-R100 1.0.0.0
3 Tuner 1
4 Playback Device 1 Chromecast 2.0.0.0
5 Audio System
6-11 省略
12,13 Reserved
14 Free Use
15 Unregisterd/Broadcast
CECフレーム
機器間ではCECフレームというコマンドで制御のやり取りをする
汎用的なコマンドとメーカー独自拡張のコマンドがある
CEC-O-MATIC : CECメッセージとCECフレームを相互に対話的に取得できる 汎用的なコマンドでも、メーカーによって実装されていない場合もある
CECフレーム: <ヘッダー(Header)><命令コード(opcode)><引数(operand)>
<ヘッダー>=<Initiatorアドレス><Destinationアドレス> : 送信元論理アドレスと送信先論理アドレスを指定する
<命令コード>: 1byteの命令毎に割り当てられたコード
<引数>: 命令コードによって長さは変化し、無い場合もある
CECフレームの例
table:HDMI CECフレームの例
CECフレーム CECメッセージ cec-client 説明 備考
<10:04 Image View On on 0 電源オン
<10:36 Standby standby 0 電源オフ
<10:44:41 User Control Pressed:Volume Up volup 音量あげる うちでは使えず
<10:44:42 User Control Pressed:Volume Down voldown 音量下げる うちでは使えず
<10:45 User Control Released volup,voldownの後で必要?
<1f:82:30:00 Active Source: {addr,3.0.0.0} as {addr}の機器をactive画面に asではRasPi(3.0.0.0)をactiveに、TV(0.0.0.0)はactiveにできない?
<ef:85 Request Active Source activeな機器を報告
<10:8f Report Power Status pow 0 電源状態の確認
01:90:00 Report Power Status On 電源Onを通知する
01:90:01 Report Power Status Off 電源Offを通知する
scan バスのデバイス情報一覧
論理アドレス: 0(TV), 1(RPI), e(Free Use), f(Broadcast)
物理アドレス: 3.0.0.0(RPI)
libcec:汎用HDMI CEC操作ライブラリ
CECを操作するライブラリ (本家, github: ) cec-clientコマンド: libcec経由でHDMI CECを使って、インタラクティブに機器を操作できる
対応OS
BSD
Linux
Apple macOS
Microsoft Windows
サポートするハードウエア
Exynos SoCのいくつか (サムスン電子)
NXP TDA995x: CuBox-iなどで使われているCEC制御チップ 利用しているソフトウエア
Kodi (XBMC) v11.0 "Eden"以降 結局、libcecはどんなハードウエアで使えるの?
amd64/i386のPCで、HDMI CECが最初から使えるようになっているものはとても少ない
VAIO, dynabook, FMVには対応機種がある/あった模様
使えても専用アプリケーションでのみ使える場合が多い
使えてもlibcecが対応している可能性は低い
arm SoCの中には、サポートしているものものある
Raspberry Pi
その他の使える可能性のあるarm: Tegra K1(tegracec), Exynos SoC, OdroidC2, CuBox
cec-clientコマンド
対話的に、CECの操作をするコマンド
コマンドラインオプション無しで実行すると、インタラクティブモードに入る
インタラクティブモードでは、外部からCECバスに流れたフレームも表示される
表示されるメッセージの種類は-d levelオプションで制限できる
table: cec-clientでよく使われるコマンドラインオプション
オプション 別名 意味
-s --single-command 標準入力に与えられた一つのコマンドだけを実行する
-m --monitor モニターモードで起動
-d {level} --log-level {level} ログレベルを指定する
-sf {file} --short-log-file {file} libCECの全てのログを{file}に書き込む
-h --help ヘルプメッセージを表示する
log level: ERROR=1,WARNING=2,NOTICE=4,TRAFFIC=8,DEBUG=16,ALL=31
code:cec-clientコマンドラインオプション
% cec-client -h
cec-client {-h|--help|-l|--list-devices|COM PORT} parameters:
-h --help Shows this help text
-l --list-devices List all devices on this system
-t --type {p|r|t|a} The device type to use. More than one is possible.
-p --port {int} The HDMI port to use as active source.
-b --base {int} The logical address of the device to which this
adapter is connected.
-f --log-file {file} Writes all libCEC log message to a file
-r --rom Read persisted settings from the EEPROM
-sf --short-log-file {file} Writes all libCEC log message without timestamps
and log levels to a file.
-d --log-level {level} Sets the log level. See cectypes.h for values.
-s --single-command Execute a single command and exit. Does not power
on devices on startup and power them off on exit.
-o --osd-name {osd name} Use a custom osd name.
-m --monitor Start a monitor-only client.
-i --info Shows information about how libCEC was compiled.
COM PORT The com port to connect to. If no COM port is given, the client tries to connect to the
first device that is detected.
Type 'h' or 'help' and press enter after starting the client to display all
available commands
cec-clientのコマンド
table: よく使うコマンド
コマンド 意味
help コマンド一覧を表示
quit cec-clientを終了する
r CECアダブタに再接続する(リセット)
scan CECバスに接続されているデバイス一覧を表示
on {address} 論理アドレス{address}の機器の電源をオンにする
standby {address} 論理アドレス{address}の機器をスタンバイ(≒電源オフ)にする
tx {bytes} {bytes}で指定されるCECフレームを実行する
as このCECアダブタ(ラズパイ)をアクティブにする(≒TVに表示)
volup/voldown/mute 音量を上げ、下げ、ミュートする
code:cec-clientコマンドhelp
help
================================================================================
Available commands:
tx {bytes} transfer bytes over the CEC line. txn {bytes} transfer bytes but don't wait for transmission ACK. on {address} power on the device with the given logical address. standby {address} put the device with the given address in standby mode. la {logical address} change the logical address of the CEC adapter. p {device} {port} change the HDMI port number of the CEC adapter. pa {physical address} change the physical address of the CEC adapter. as make the CEC adapter the active source. is mark the CEC adapter as inactive source. osd {addr} {string} set OSD message on the specified device. ver {addr} get the CEC version of the specified device. ven {addr} get the vendor ID of the specified device. lang {addr} get the menu language of the specified device. pow {addr} get the power status of the specified device. name {addr} get the OSD name of the specified device. poll {addr} poll the specified device. lad lists active devices on the bus ad {addr} checks whether the specified device is active. at {type} checks whether the specified device type is active. sp {addr} makes the specified physical address active. spl {addr} makes the specified logical address active. volup send a volume up command to the amp if present voldown send a volume down command to the amp if present mute send a mute/unmute command to the amp if present self show the list of addresses controlled by libCEC scan scan the CEC bus and display device info mon {1|0} enable or disable CEC bus monitoring. cec-clientの利用例
code:TVの電源を入れる
% echo "on 0" | cec-client -s -d 1
code:TVの電源を切る
% echo "standby 0" |cec-client -d 1 -s
code:TVの電源状態を確認する
% echo "pow 0" | cec-client -s -d 1
opening a connection to the CEC adapter...
power status: on
# or, unknown, standby
code:TVのアクティブ画面を変更する;Chromecast(2.0.0.0)に変更する場合
% echo "tx 1f:82:20:00"|cec-client -s -d 1
code:機器のCECバージョンを確認する;Chromecast(4)の場合
% cec-client
tx 24:9f
TRAFFIC: 5765 >> 42:9e:05 DEBUG: 5765 Playback 1 (4): CEC version 1.4 DEBUG: 5765 device Playback 1 (4) status changed to present after command cec version DEBUG: 5766 >> Playback 1 (4) -> Recorder 2 (2): cec version (9E) code:リモコンのキー入力;ラズパイがアクティブの時
DEBUG: 278031331 SetCurrentButton play (44) D:0ms cur:4a6d98 DEBUG: 278031331 key pressed: play (44) current(ff) duration(0) DEBUG: 278031331 Changed key play (44) D:0ms cur:ff DEBUG: 278031331 CheckKeypressTimeout T:430152.778 DEBUG: 278031331 Key play: idle (duration:0) (44) timeout:1943006428ms (rel:500,rep:0,prs:500,rel:0) DEBUG: 278031331 >> TV (0) -> Recorder 2 (2): user control pressed (44) DEBUG: 278031699 key released: play (44) D:368ms DEBUG: 278031699 >> TV (0) -> Recorder 2 (2): vendor remote button up (8B) DEBUG: 278100224 SetCurrentButton stop (45) D:0ms cur:4a6d98 DEBUG: 278100224 key pressed: stop (45) current(ff) duration(0) DEBUG: 278100224 Changed key stop (45) D:0ms cur:ff DEBUG: 278100224 CheckKeypressTimeout T:430221.671 DEBUG: 278100224 Key stop: idle (duration:0) (45) timeout:1943006428ms (rel:1000,rep:0,prs:500,rel:0) DEBUG: 278100224 >> TV (0) -> Recorder 2 (2): user control pressed (44) DEBUG: 278100495 CheckKeypressTimeout T:430221.942 DEBUG: 278100495 Key stop: idle (duration:0) (45) timeout:1943006428ms (rel:729,rep:0,prs:229,rel:0) DEBUG: 278100495 >> TV (0) -> Recorder 2 (2): vendor remote button up (8B) DEBUG: 278101228 CheckKeypressTimeout T:430222.675 DEBUG: 278101228 Key unknown: released (duration:1004) (ff) timeout:0ms (rel:1000,rep:0,prs:0,rel:0) DEBUG: 278132326 SetCurrentButton Fast forward (49) D:0ms cur:4a6d98 DEBUG: 278132326 key pressed: Fast forward (49) current(ff) duration(0) DEBUG: 278132326 Changed key Fast forward (49) D:0ms cur:ff DEBUG: 278132326 key pressed: Fast forward (49, 0) DEBUG: 278132326 CheckKeypressTimeout T:430253.773 DEBUG: 278132326 Key Fast forward: idle (duration:0) (49) timeout:1943006428ms (rel:500,rep:0,prs:500,rel:0) DEBUG: 278132327 >> TV (0) -> Recorder 2 (2): user control pressed (44) DEBUG: 278132597 key released: Fast forward (49) D:271ms DEBUG: 278132597 >> TV (0) -> Recorder 2 (2): vendor remote button up (8B) cec-client on FreeBSD/Raspberry Pi arm 11.2R
code: shell
% dmesg
FreeBSD rpi-b 11.2-RELEASE FreeBSD 11.2-RELEASE #0 r335510: Fri Jun 22 02:35:12 UTC 2018 root@releng2.nyi.freebsd.org:/usr/obj/arm.armv6/usr/src/sys/RPI-B arm % pkg info|grep cec
libcec-4.0.2_2 Library to control Pulse-Eight's HDMI-CEC adapter
どうも、/dev/vchiqを使っているらしい
code:一般ユーザでは実行できない
% cec-client
No device type given. Using 'recording device'
* failed to open vchiq instance
code:vchiq関連のデバイスは以下の通り
simplebus0: <Flattened device tree simple bus> mem 0x20000000-0x20ffffff on ofwbus0t
vchiq0: <BCM2835 VCHIQ> mem 0xb800-0xb84f irq 29 on simplebus0
vchiq: local ver 8 (min 3), remote ver 8.
pcm0: <VCHIQ audio> on vchiq0
code:/dev/vchiqのパーミッション
% ls -l /dev/vchiq
crw------- 1 root wheel 0x2c Jun 23 04:58 /dev/vchiq
code:現在のCECバスにぶら下がっているデバイスを見る
% echo "scan" | sudo cec-client -s -d 1
opening a connection to the CEC adapter...
requesting CEC bus information ...
CEC bus information
===================
address: 0.0.0.0
active source: yes
vendor: Sharp
osd string: TV
CEC version: unknown
power status: on
language: jpn
address: 3.0.0.0
active source: no
vendor: Pulse Eight
osd string: CECTester
CEC version: 1.4
power status: on
language: eng
address: 1.0.0.0
active source: no
vendor: Toshiba
osd string: RD-R100
CEC version: 1.3a
power status: on
language: ???
address: 2.0.0.0
active source: no
vendor: Google
osd string: Chromecast
CEC version: 1.4
power status: on
language: ???
currently active source: TV (0)
デモ: できるかな?
どこまでできるかな?
TVの電源をオンオフ
TVの電源オフ時にラズパイのキーボードを触ると、TVの電源が入った!!
画面のアクティブを変更する
リモコン入力ができているのを確認する
できたこと
現在、TVがついているか調べて、ついていたら動画再生をやめる
echo "pow 0" | cec-client -s -d 1|grep power|cut -d" " -f 3
再生前にTVの電源を入れる
echo "on 0" |cec-client -d 1 -s
YouTube動画の再生時間終了後にTVの電源を切る
echo "standby 0" |cec-client -d 1 -s
本当はやりたかったこと
アクティブをTVに変える(Active Source); 他の機器に変えるのは可能
動画終了時にTVに戻しておきたかった
TVの音量を変える(volup,voldown,mute)
エクササイズ時だけ、音量をあげたかった
echo "volup" |cec-client -d 1 -s
TVのリモコンを入力として使う (User Control)
気に入らない動画だったら変えるとか
ラズパイがアクティブな時は使えるけど、Chromecastがアクティブな時に操作したいのでいまいちか?
赤外線リモコンとして扱った方が早い?
TVのアクティブを確認(Request Active Source)
動画終了時のアクティブを確認して、Chromecast以外ならTVの電源を消さない
echo "tx 20:85"|cec-client -d 1 -s
おわりに
苦し紛れに使ったHDMI CECで、とりあえずひとつネタができました
HDMI CECで遊びたかったら、Raspberry Piがお手軽です
うちの安いTVでは、ほとんどのコマンドが使えずに悲しかったです
まだ残る疑問
リモコン入力は、アクティブの機器にだけ来るのが正しいの?
なぜ、TVにアクティブを変更するのはできないの?
Q & A
そも、HDMIってどこの規格なの?
7社共同規格 (Silicon Image、ソニー、東芝、トムソン、パナソニック、日立製作所、フィリップス)
使用には、年会費とロイヤリティ(使用料)が必要
物理アドレス大量なのに、論理アドレス13ぐらいで大丈夫なの?
MACアドレスみたいなユニークなものないの?